package com.cxp.serverdemo.config;

import com.cxp.serverdemo.bean.sys.bean.Menu;
import com.cxp.serverdemo.bean.sys.bean.Role;
import com.cxp.serverdemo.service.MenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.List;

/**
 * DESC：当访问一个url时返回这个url所需要的访问权限
 * RETURN:：给spring security返回一个权限列表，供决策管理器（AccessDecisionManager）做验证
 * Created by sang on 2019/1/15.
 */

@Component
public class CustomMetadataSource implements FilterInvocationSecurityMetadataSource {
    @Autowired
    MenuService menuService;
    private static final Logger logger = LoggerFactory.getLogger(CustomMetadataSource.class);

    AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        String requestUrl = ((FilterInvocation) o).getRequestUrl();
        logger.info("CustomMetadataSource.requestUrl-------" + requestUrl);
        List<Menu> allMenu = menuService.getAllMenu();
        logger.info("CustomMetadataSource.allMenu.get(0).getRoles()-------" + allMenu.get(0).getRoles().toString());
        for (Menu menu : allMenu) {
            logger.info("CustomMetadataSource.menu.getRoles()-------" + menu.getRoles().toString());
            if (antPathMatcher.match(menu.getPath(), requestUrl) && menu.getRoles().size()>0) { //判断访问的URL与当前URL是否相等，并且当前URL已分配有角色
                List<Role> roles = menu.getRoles();
                logger.info("CustomMetadataSource.menu.roles-------" + roles.toString());
                int size = roles.size();
                String[] values = new String[size];
                for (int i = 0; i < size; i++) {
                    values[i] = "ROLE_" + roles.get(i).getName();
                }
                logger.info("CustomMetadataSource.menu.roles.values-------" + values.toString());
                return SecurityConfig.createList(values); //返回访问URL的角色（权限）集合
            }
        }
        //没有匹配上的资源，都是登录访问
        return SecurityConfig.createList("ROLE_LOGIN");
    }

    /*
    * 如果返回了所有定义的权限资源
    * Spring Security会在启动时校验每个ConfigAttribute是否配置正确
    * 不需要校验直接返回null
    * */
    //这里是获取所有的系统URL，可以在系统启动时，将这个集合放有缓存中，之后验证用户访问权限时就不用再去访问数据库，
    //直接取这个结果来作对比，不过这个需要手支刷新缓存，否则但资源信息改变时，这个集合就成了脏数据 ，会出错。
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }


    //返回类对象是否支持校验，web项目一般使用FilterInvocation来判断，或者直接返回true
    @Override
    public boolean supports(Class<?> aClass) {
        return FilterInvocation.class.isAssignableFrom(aClass);
    }
}
